// 全局变量
let scene, camera, renderer, controls;
let warehouse, shelves = [];
let selectedLocation = null;
let selectedBox = null;
let isThreeJsInitialized = false;
let animationFrameId = null;
let agvs = []; // 存储AGV对象
let initRetryCount = 0;
const MAX_RETRY_COUNT = 20; // 最大重试次数
// 货位数据配置
let defaultData = {
  // 格式: "货位号": { 产品名称, 数量, 状态 }
  "A5-B3-4": {
    productName: "键盘",
    quantity: 5,
    status: "正常"
  },
  "A5-B5-4": {
    productName: "键盘",
    quantity: 5,
    status: "异常1"
  },
  "A5-B2-4": {
    productName: "键盘",
    quantity: 5,
    status: "异常2"
  },
  // 可以继续添加更多货位数据...
};
// 导出初始化和清理函数
window.initWarehouse3D = function (locationData = defaultData) {
  console.log("locationData1111", locationData);

  // 确保THREE已经加载
  if (typeof THREE === 'undefined') {
    if (initRetryCount < MAX_RETRY_COUNT) {
      initRetryCount++;
      setTimeout(window.initWarehouse3D, 100);
      return;
    } else {
      return;
    }
  }

  // 确保OrbitControls已经加载
  if (typeof THREE.OrbitControls === 'undefined') {
    if (initRetryCount < MAX_RETRY_COUNT) {
      initRetryCount++;
      setTimeout(window.initWarehouse3D, 100);
      return;
    } else {
      return;
    }
  }

  // 重置重试计数
  initRetryCount = 0;

  // 如果已经初始化，先清理
  if (isThreeJsInitialized) {
    window.cleanupWarehouse3D();
  }

  try {
    init(locationData);
    isThreeJsInitialized = true;
    animate();
  } catch (error) {
  }
};

window.cleanupWarehouse3D = function () {
  if (animationFrameId) {
    cancelAnimationFrame(animationFrameId);
    animationFrameId = null;
  }

  // 移除事件监听器
  window.removeEventListener('resize', onWindowResize);

  // 清理Three.js资源
  if (renderer) {
    renderer.dispose();
    const container = document.getElementById('warehouse3d');
    if (container && container.contains(renderer.domElement)) {
      container.removeChild(renderer.domElement);
    }
    renderer = null;
  }

  if (controls) {
    controls.dispose();
    controls = null;
  }

  // 清除场景中的所有对象
  if (scene) {
    while (scene.children.length > 0) {
      const object = scene.children[0];
      if (object.geometry) {
        object.geometry.dispose();
      }
      if (object.material) {
        if (Array.isArray(object.material)) {
          object.material.forEach(material => material.dispose());
        } else {
          object.material.dispose();
        }
      }
      scene.remove(object);
    }
    scene = null;
  }

  // 重置变量
  camera = null;
  shelves = [];
  selectedLocation = null;
  selectedBox = null;
  isThreeJsInitialized = false;
  agvs = [];
};

// 初始化Three.js场景
function init (locationData) {
  console.log('Initializing Three.js scene');

  // 创建场景
  scene = new THREE.Scene();
  scene.background = new THREE.Color(0xf0f2f5);

  // 创建相机
  const container = document.getElementById('warehouse3d');
  if (!container) {
    throw new Error('Container not found');
  }

  const aspect = container.clientWidth / container.clientHeight;
  camera = new THREE.PerspectiveCamera(75, aspect, 0.1, 1000);
  camera.position.set(0, 20, 20);  // 相机位于正前方，稍微高一点的位置
  camera.lookAt(0, 0, 0);

  // 创建渲染器
  renderer = new THREE.WebGLRenderer({
    antialias: true,
    alpha: true
  });
  renderer.setSize(container.clientWidth, container.clientHeight);
  renderer.setPixelRatio(window.devicePixelRatio);

  // 配置阴影
  renderer.shadowMap.enabled = true;
  renderer.shadowMap.type = THREE.PCFSoftShadowMap; // 使用更柔和的阴影
  container.appendChild(renderer.domElement);

  // 添加轨道控制器
  controls = new THREE.OrbitControls(camera, renderer.domElement);
  controls.enableDamping = true;
  controls.dampingFactor = 0.05;
  controls.enableZoom = true;
  controls.minDistance = 5;
  controls.maxDistance = 50;
  controls.maxPolarAngle = Math.PI / 2;

  // 添加环境光和平行光
  const ambientLight = new THREE.AmbientLight(0xffffff, 0.6);
  scene.add(ambientLight);

  // 主平行光（用于阴影）
  const mainLight = new THREE.DirectionalLight(0xffffff, 0.8);
  mainLight.position.set(10, 10, 10);
  mainLight.castShadow = true;

  // 配置阴影参数
  mainLight.shadow.mapSize.width = 2048;  // 增加阴影贴图分辨率
  mainLight.shadow.mapSize.height = 2048;
  mainLight.shadow.camera.near = 0.5;
  mainLight.shadow.camera.far = 50;
  mainLight.shadow.camera.left = -25;
  mainLight.shadow.camera.right = 25;
  mainLight.shadow.camera.top = 25;
  mainLight.shadow.camera.bottom = -25;
  mainLight.shadow.bias = -0.001;  // 减少阴影失真

  scene.add(mainLight);

  // 添加辅助平行光（不产生阴影，只用于照亮）
  const fillLight = new THREE.DirectionalLight(0xffffff, 0.3);
  fillLight.position.set(-5, 8, -10);
  scene.add(fillLight);

  // 创建地板
  // 创建地板
  const floorGeometry = new THREE.PlaneGeometry(50, 50);
  const floorMaterial = new THREE.MeshStandardMaterial({
    color: 0xe0e0e0,
    roughness: 0.8,
    metalness: 0.2
  });
  const floor = new THREE.Mesh(floorGeometry, floorMaterial);
  floor.rotation.x = -Math.PI / 2;
  floor.receiveShadow = false;  // 禁用地板接收阴影
  scene.add(floor);
  // 创建货架
  createShelves(locationData);

  // 添加坐标轴辅助
  const axesHelper = new THREE.AxesHelper(5);
  scene.add(axesHelper);

  // 添加网格辅助
  const gridHelper = new THREE.GridHelper(50, 50);
  scene.add(gridHelper);

  // 添加事件监听
  window.addEventListener('resize', onWindowResize, false);
  renderer.domElement.addEventListener('click', onMouseClick, false);

  // 创建四台AGV，设置不同的初始位置
  const agvStartPositions = [
    { pos: [-22, 0, -22], targetIndex: 0 },
    { pos: [-22, 0, 22], targetIndex: 1 },
    { pos: [22, 0, 22], targetIndex: 2 },
    { pos: [22, 0, -22], targetIndex: 3 }
  ];

  agvStartPositions.forEach((config, index) => {
    const agv = createAGV(...config.pos);
    agv.userData.targetIndex = config.targetIndex;
    agv.userData.speed = 0.05 + (index * 0.01); // 略微不同的速度
    scene.add(agv);
    agvs.push(agv);
  });
}

// 创建货架
// function createShelves (locationData) {
//   // 创建5x5网格的货架
//   for (let x = -20; x <= 20; x += 5) {
//     for (let z = -20; z <= 20; z += 5) {
//       createShelfUnit(x, z, locationData);
//     }
//   }
// }
// 创建货架（横向连在一起）
// 创建多排横向货架
function createShelves (locationData) {
  const shelfLength = 2; // 每个货架单元的长度
  const shelfWidth = 2;  // 每个货架单元的宽度
  const shelfHeight = 4; // 货架高度
  const rowCount = 5;    // 货架排数
  const rowSpacing = 6;  // 排与排之间的间距

  // 创建多排横向货架
  for (let row = 0; row < rowCount; row++) {
    const z = -((rowCount - 1) * rowSpacing) / 2 + row * rowSpacing; // 居中排列
    createHorizontalShelfRow(-20, z, shelfLength, shelfWidth, shelfHeight, locationData, row);
  }
}
// 创建横向的一排货架
function createHorizontalShelfRow (startX, z, shelfLength, shelfWidth, shelfHeight, locationData, rowIndex) {
  const shelfCount = 20; // 每排货架单元数量
  const spacing = 0;    // 货架单元之间的间距（设为0表示完全连在一起）
  const totalWidth = shelfCount * shelfLength;
  startX = -totalWidth / 2; // 居中排列

  for (let i = 0; i < shelfCount; i++) {
    const x = startX + i * (shelfLength + spacing);
    createShelfUnit(x, z, shelfLength, shelfWidth, shelfHeight, locationData, rowIndex, i);
  }
}

// 创建单个货架单元
function createShelfUnit (x, z, length, width, height, locationData, rowIndex, colIndex) {
  // 创建货架框架
  const frameGeometry = new THREE.BoxGeometry(0.2, height, width);
  const frameMaterial = new THREE.MeshStandardMaterial({
    color: 0x4a5568,
    roughness: 0.7,
    metalness: 0.3
  });

  // 创建左右支柱
  const leftFrame = new THREE.Mesh(frameGeometry, frameMaterial);
  const rightFrame = new THREE.Mesh(frameGeometry, frameMaterial);
  leftFrame.position.set(x - length / 2, height / 2, z);
  rightFrame.position.set(x + length / 2, height / 2, z);
  scene.add(leftFrame);
  scene.add(rightFrame);

  // 创建层板和货箱
  const shelfLevels = 4; // 4层
  const levelHeight = 0.8; // 每层高度
  const startY = 0.6; // 第一层的起始高度

  for (let level = 0; level < shelfLevels; level++) {
    // 创建层板（横向）
    const shelfGeometry = new THREE.BoxGeometry(length, 0.1, width);
    const shelfMaterial = new THREE.MeshStandardMaterial({
      color: 0x4a5568,
      roughness: 0.7,
      metalness: 0.3
    });
    const shelf = new THREE.Mesh(shelfGeometry, shelfMaterial);
    shelf.position.set(x, startY + level * levelHeight, z);
    scene.add(shelf);

    // 库位编号格式: "排号-列号-层号" 例如: "R1-C3-L2"
    const locationNumber = `R${rowIndex + 1}-C${colIndex + 1}-L${level + 1}`;

    // 添加库位编号标签（前后各一个）
    createLocationLabel(locationNumber, x, startY + level * levelHeight + 0.05, z + width / 2 + 0.05, 0);
    createLocationLabel(locationNumber, x, startY + level * levelHeight + 0.05, z - width / 2 - 0.05, Math.PI);

    // 检查该货位是否有数据
    if (locationData[locationNumber]) {
      const { productName, quantity, status } = locationData[locationNumber];

      // 只生成一个箱子，不再根据数量生成多个
      const boxWidth = 1.0;   // 新的宽度
      const boxHeight = 0.7;  // 新的高度
      const boxDepth = 1.0;   // 新的深度

      const boxX = x;  // 居中放置
      const boxZ = z;  // 居中放置

      const boxGeometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
      const boxMaterial = new THREE.MeshStandardMaterial({
        color: getColorForStatus(status),
        roughness: 0.7,
        metalness: 0.1,
        map: createBoxTexture()
      });

      const box = new THREE.Mesh(boxGeometry, boxMaterial);
      box.position.set(boxX, startY + level * levelHeight + boxHeight / 2 + 0.05, boxZ);
      box.castShadow = false;  // 禁用阴影投射
      box.receiveShadow = false;  // 禁用阴影接收
      box.userData = {
        type: 'box',
        productName: productName,
        location: locationNumber,
        quantity: quantity,
        status: status
      };

      scene.add(box);

      // 添加封条和标签
      const tapeGroup = addSealingTapes(box, boxWidth, boxHeight, boxDepth, boxX, startY + level * levelHeight + boxHeight / 2 + 0.05, boxZ);
      scene.add(tapeGroup);

      const labelY = startY + level * levelHeight + boxHeight / 2 + 0.05;
      const frontLabel = createProductLabel(productName, boxX, labelY, boxZ + boxDepth / 2 + 0.01, 0, 0.45);
      const backLabel = createProductLabel(productName, boxX, labelY, boxZ - boxDepth / 2 - 0.01, Math.PI, 0.45);
      scene.add(frontLabel);
      scene.add(backLabel);
    }
  }

  // 创建后挡板
  const backGridGeometry = new THREE.PlaneGeometry(length, height);
  const backGridMaterial = new THREE.MeshStandardMaterial({
    color: 0x4a5568,
    wireframe: true,
    wireframeLinewidth: 2
  });
  const backGrid = new THREE.Mesh(backGridGeometry, backGridMaterial);
  backGrid.position.set(x, height / 2, z - width / 2);
  backGrid.rotation.y = Math.PI / 2;
  scene.add(backGrid);

  const shelfUnit = new THREE.Group();
  shelfUnit.add(leftFrame);
  shelfUnit.add(rightFrame);
  shelfUnit.position.set(x, 0, z);

  shelfUnit.userData = {
    type: 'shelf',
    id: `shelf_${rowIndex}_${colIndex}`,
    location: `R${rowIndex + 1}-C${colIndex + 1}`,
    status: '已占用'
  };

  shelves.push(shelfUnit);
}


// 创建单个货架单元
// function createShelfUnit (x, z, locationData) {
//   // 创建货架框架（这部分保持不变）
//   const frameGeometry = new THREE.BoxGeometry(0.2, 4, 3);
//   const frameMaterial = new THREE.MeshStandardMaterial({
//     color: 0x4a5568,
//     roughness: 0.7,
//     metalness: 0.3
//   });

//   // 创建左右支柱（保持不变）
//   const leftFrame = new THREE.Mesh(frameGeometry, frameMaterial);
//   const rightFrame = new THREE.Mesh(frameGeometry, frameMaterial);
//   leftFrame.position.set(x - 1, 2, z);
//   rightFrame.position.set(x + 1, 2, z);
//   leftFrame.castShadow = false;
//   rightFrame.castShadow = false;
//   scene.add(leftFrame);
//   scene.add(rightFrame);

//   // 创建层板和货箱
//   const shelfLevels = 4; // 4层
//   const levelHeight = 0.8; // 每层高度
//   const startY = 0.6; // 第一层的起始高度

//   for (let level = 0; level < shelfLevels; level++) {
//     // 创建层板（保持不变）
//     const shelfGeometry = new THREE.BoxGeometry(2.2, 0.1, 3);
//     const shelfMaterial = new THREE.MeshStandardMaterial({
//       color: 0x4a5568,
//       roughness: 0.7,
//       metalness: 0.3
//     });
//     const shelf = new THREE.Mesh(shelfGeometry, shelfMaterial);
//     shelf.position.set(x, startY + level * levelHeight, z);
//     shelf.castShadow = false;
//     shelf.receiveShadow = false;
//     scene.add(shelf);

//     // 库位编号
//     const locationNumber = `A${Math.floor((x + 15) / 5)}-B${Math.floor((z + 15) / 5)}-${level + 1}`;

//     // 添加四个方向的库位编号标签（保持不变）
//     createLocationLabel(locationNumber, x, startY + level * levelHeight + 0.05, z + 1.55, 0);
//     createLocationLabel(locationNumber, x, startY + level * levelHeight + 0.05, z - 1.55, Math.PI);
//     createLocationLabel(locationNumber, x - 1.15, startY + level * levelHeight + 0.05, z, Math.PI / 2);
//     createLocationLabel(locationNumber, x + 1.15, startY + level * levelHeight + 0.05, z, -Math.PI / 2);


//     // 检查该货位是否有数据
//     if (locationData[locationNumber]) {
//       const { productName, quantity, status } = locationData[locationNumber];
//       const boxCount = Math.min(Math.floor(quantity / 10) + 1, 4); // 根据数量决定箱子数量

//       const boxWidth = 0.7;
//       const boxHeight = 0.5;
//       const boxDepth = 0.7;
//       const startX = x - 0.7;
//       const startZ = z - 0.9;
//       const spacing = 0.15;

//       // 创建箱子（只修改数据部分）
//       for (let i = 0; i < boxCount; i++) {
//         const boxX = startX + (i % 2) * (boxWidth + spacing);
//         const boxZ = startZ + Math.floor(i / 2) * (boxDepth + spacing);

//         const boxGeometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
//         const boxMaterial = new THREE.MeshStandardMaterial({
//           color: getColorForStatus(status),
//           roughness: 0.7,
//           metalness: 0.1,
//           map: createBoxTexture()
//         });
//         const box = new THREE.Mesh(boxGeometry, boxMaterial);
//         box.position.set(boxX, startY + level * levelHeight + boxHeight / 2 + 0.05, boxZ);
//         box.castShadow = true;
//         box.receiveShadow = true;

//         // 使用外部配置的数据
//         box.userData = {
//           type: 'box',
//           productName: productName,
//           location: locationNumber,
//           quantity: quantity,
//           status: status
//         };
//         scene.add(box);

//         // 其余代码（封条、标签等）保持不变...
//         const tapeGroup = addSealingTapes(
//           box, boxWidth, boxHeight, boxDepth,
//           boxX, startY + level * levelHeight + boxHeight / 2 + 0.05, boxZ
//         );
//         scene.add(tapeGroup);

//         const labelY = startY + level * levelHeight + boxHeight / 2 + 0.05;
//         const labelOffset = 0.01;

//         const frontLabel = createProductLabel(productName, boxX, labelY, boxZ + boxDepth / 2 + labelOffset, 0, 0.45);
//         scene.add(frontLabel);

//         const backLabel = createProductLabel(productName, boxX, labelY, boxZ - boxDepth / 2 - labelOffset, Math.PI, 0.45);
//         scene.add(backLabel);

//         const leftLabel = createProductLabel(productName, boxX - boxWidth / 2 - labelOffset, labelY, boxZ, Math.PI / 2, 0.45);
//         scene.add(leftLabel);

//         const rightLabel = createProductLabel(productName, boxX + boxWidth / 2 + labelOffset, labelY, boxZ, -Math.PI / 2, 0.45);
//         scene.add(rightLabel);
//       }
//     }
//   }

//   // 其余代码（后挡板、货架信息等）保持不变...
//   const backGridGeometry = new THREE.PlaneGeometry(2.2, 4);
//   const backGridMaterial = new THREE.MeshStandardMaterial({
//     color: 0x4a5568,
//     wireframe: true,
//     wireframeLinewidth: 2
//   });
//   const backGrid = new THREE.Mesh(backGridGeometry, backGridMaterial);
//   backGrid.position.set(x, 2, z + 1.45);
//   backGrid.castShadow = false;
//   backGrid.receiveShadow = false;
//   scene.add(backGrid);

//   const shelfUnit = new THREE.Group();
//   shelfUnit.add(leftFrame);
//   shelfUnit.add(rightFrame);
//   shelfUnit.position.set(x, 0, z);

//   shelfUnit.userData = {
//     type: 'shelf',
//     id: `shelf_${x}_${z}`,
//     location: `A${Math.floor((x + 15) / 5)}-B${Math.floor((z + 15) / 5)}`,
//     status: Object.keys(locationData).some(key => key.startsWith(`A${Math.floor((x + 15) / 5)}-B${Math.floor((z + 15) / 5)}`))
//       ? '已占用' : '空闲'
//   };

//   shelves.push(shelfUnit);
// }

// 创建箱子纹理
function createBoxTexture () {
  const canvas = document.createElement('canvas');
  const context = canvas.getContext('2d');
  canvas.width = 256;
  canvas.height = 256;

  // 绘制纸箱底色
  context.fillStyle = '#e6c66e';  // 更自然的纸箱颜色
  context.fillRect(0, 0, canvas.width, canvas.height);

  // 添加边缘阴影效果
  const gradient = context.createLinearGradient(0, 0, canvas.width, canvas.height);
  gradient.addColorStop(0, 'rgba(0,0,0,0.1)');
  gradient.addColorStop(0.2, 'rgba(0,0,0,0)');
  gradient.addColorStop(0.8, 'rgba(0,0,0,0)');
  gradient.addColorStop(1, 'rgba(0,0,0,0.1)');
  context.fillStyle = gradient;
  context.fillRect(0, 0, canvas.width, canvas.height);

  const texture = new THREE.CanvasTexture(canvas);
  texture.needsUpdate = true;
  return texture;
}
// 根据状态获取颜色
function getColorForStatus (status) {
  switch (status) {
    case '正常': return 0x68d391; // 绿色
    case '异常1': return 0xfc8181; // 红色
    case '异常2': return 0xf6ad55; // 橙色
    default: return 0x68d391; // 默认颜色
  }
}
// 创建封条
function createSealingTape (width, height, depth) {
  const tapeGeometry = new THREE.BoxGeometry(width, height, depth);
  const tapeMaterial = new THREE.MeshStandardMaterial({
    color: 0xf5f5f5,  // 浅白色封条
    roughness: 0.5,
    metalness: 0.1,
    transparent: true,
    opacity: 0.9
  });
  return new THREE.Mesh(tapeGeometry, tapeMaterial);
}

// 为箱子添加封条
function addSealingTapes (box, boxWidth, boxHeight, boxDepth, x, y, z) {
  const tapeWidth = 0.03; // 封条宽度
  const tapeThickness = 0.001; // 减小封条厚度

  // 创建封条组
  const tapeGroup = new THREE.Group();

  // 顶部封条（十字形）
  const topTapeH = createSealingTape(boxWidth + tapeThickness, tapeWidth, tapeThickness);
  const topTapeV = createSealingTape(tapeWidth, tapeWidth, boxDepth + tapeThickness);
  topTapeH.position.set(0, boxHeight / 2 + tapeThickness / 2, 0);
  topTapeV.position.set(0, boxHeight / 2 + tapeThickness / 2, 0);
  tapeGroup.add(topTapeH);
  tapeGroup.add(topTapeV);

  // 底部封条（十字形）
  const bottomTapeH = createSealingTape(boxWidth + tapeThickness, tapeWidth, tapeThickness);
  const bottomTapeV = createSealingTape(tapeWidth, tapeWidth, boxDepth + tapeThickness);
  bottomTapeH.position.set(0, -boxHeight / 2 - tapeThickness / 2, 0);
  bottomTapeV.position.set(0, -boxHeight / 2 - tapeThickness / 2, 0);
  tapeGroup.add(bottomTapeH);
  tapeGroup.add(bottomTapeV);

  // 前后封条（垂直）
  const frontTape = createSealingTape(tapeWidth, boxHeight + tapeThickness, tapeThickness);
  const backTape = createSealingTape(tapeWidth, boxHeight + tapeThickness, tapeThickness);
  frontTape.position.set(0, 0, boxDepth / 2 + tapeThickness / 2);
  backTape.position.set(0, 0, -boxDepth / 2 - tapeThickness / 2);
  tapeGroup.add(frontTape);
  tapeGroup.add(backTape);

  // 左右封条（垂直）
  const leftTape = createSealingTape(tapeThickness, boxHeight + tapeThickness, tapeWidth);
  const rightTape = createSealingTape(tapeThickness, boxHeight + tapeThickness, tapeWidth);
  leftTape.position.set(-boxWidth / 2 - tapeThickness / 2, 0, 0);
  rightTape.position.set(boxWidth / 2 + tapeThickness / 2, 0, 0);
  tapeGroup.add(leftTape);
  tapeGroup.add(rightTape);

  // 设置整个封条组的位置
  tapeGroup.position.set(x, y, z);

  return tapeGroup;
}

// 创建产品标签
function createProductLabel (text, x, y, z, rotation = 0, scale = 1) {
  const canvas = document.createElement('canvas');
  const context = canvas.getContext('2d');

  canvas.width = 256;
  canvas.height = 64;

  // 设置背景
  context.fillStyle = '#ffffff';
  context.fillRect(0, 0, canvas.width, canvas.height);

  // 添加边框
  context.strokeStyle = '#000000';
  context.lineWidth = 2;
  context.strokeRect(0, 0, canvas.width, canvas.height);

  // 设置文本样式
  context.font = 'bold 32px Arial';
  context.fillStyle = '#0066cc'; // 蓝色文字
  context.textAlign = 'center';
  context.textBaseline = 'middle';

  // 如果是后面的标签，翻转文字
  if (Math.abs(rotation) === Math.PI) {
    context.save();
    context.translate(canvas.width / 2, canvas.height / 2);
    context.rotate(Math.PI);
    context.fillText(text, 0, 0);
    context.restore();
  } else {
    context.fillText(text, canvas.width / 2, canvas.height / 2);
  }

  const texture = new THREE.CanvasTexture(canvas);
  texture.needsUpdate = true;

  const material = new THREE.MeshBasicMaterial({
    map: texture,
    transparent: true,
    side: THREE.DoubleSide
  });

  const geometry = new THREE.PlaneGeometry(0.6 * scale, 0.15 * scale);
  const label = new THREE.Mesh(geometry, material);

  label.position.set(x, y, z);
  label.rotation.y = rotation;

  return label;
}

// 创建库位标签
function createLocationLabel (text, x, y, z, rotation = 0) {
  const canvas = document.createElement('canvas');
  const context = canvas.getContext('2d');
  canvas.width = 128;
  canvas.height = 32;

  // 设置背景
  context.fillStyle = '#ffffff';
  context.fillRect(0, 0, canvas.width, canvas.height);

  // 添加边框
  context.strokeStyle = '#000000';
  context.lineWidth = 2;
  context.strokeRect(0, 0, canvas.width, canvas.height);

  // 设置文本样式
  context.font = 'bold 24px Arial';
  context.fillStyle = '#000000';
  context.textAlign = 'center';
  context.textBaseline = 'middle';

  // 如果是后面的标签，翻转文字
  if (Math.abs(rotation) === Math.PI) {
    context.save();
    context.translate(canvas.width / 2, canvas.height / 2);
    context.rotate(Math.PI);
    context.fillText(text, 0, 0);
    context.restore();
  } else {
    context.fillText(text, canvas.width / 2, canvas.height / 2);
  }

  const texture = new THREE.CanvasTexture(canvas);
  texture.needsUpdate = true;

  const material = new THREE.MeshBasicMaterial({
    map: texture,
    transparent: true,
    side: THREE.DoubleSide
  });

  const geometry = new THREE.PlaneGeometry(0.8, 0.2);
  const label = new THREE.Mesh(geometry, material);

  label.position.set(x, y, z);
  label.rotation.y = rotation;

  scene.add(label);
}

// 窗口大小调整处理
function onWindowResize () {
  const container = document.getElementById('warehouse3d');
  if (!container || !camera || !renderer) return;

  camera.aspect = container.clientWidth / container.clientHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(container.clientWidth, container.clientHeight);
}

// 鼠标点击事件处理
function onMouseClick (event) {
  if (!scene || !camera) return;

  const raycaster = new THREE.Raycaster();
  const mouse = new THREE.Vector2();
  const popup = document.getElementById('popup');

  // 计算鼠标位置
  const rect = renderer.domElement.getBoundingClientRect();
  mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
  mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;

  raycaster.setFromCamera(mouse, camera);

  // 检测射线与场景中物体的交叉
  const intersects = raycaster.intersectObjects(scene.children, true);

  if (intersects.length > 0) {
    const clickedObject = intersects[0].object;

    // 检查点击的是否是盒子或货架（或它们的子元素）
    const isBox = clickedObject.userData.type === 'box' ||
      (clickedObject.parent && clickedObject.parent.userData.type === 'box');
    const isShelf = clickedObject.userData.type === 'shelf' ||
      (clickedObject.parent && clickedObject.parent.userData.type === 'shelf');

    if (isBox || isShelf) {
      // 重置之前的选中状态
      resetSelection();

      // 处理货架点击
      if (isShelf) {
        const shelfUnit = clickedObject.userData.type === 'shelf' ? clickedObject : clickedObject.parent;

        // 高亮选中的货架
        shelfUnit.children.forEach(child => {
          if (child.material && !child.material.wireframe) {
            child.material.color.setHex(0x3182ce);
          }
        });
        selectedLocation = shelfUnit;

        // 显示弹窗并传递对象引用
        showPopup(shelfUnit.userData, event, shelfUnit);
      }
      // 处理箱子点击
      else if (isBox) {
        const box = clickedObject.userData.type === 'box' ? clickedObject : clickedObject.parent;

        // 保存原始材质
        box.userData.originalColor = box.material.color.getHex();
        // 高亮选中的箱子
        box.material.color.setHex(0x3182ce);
        selectedBox = box;

        // 显示弹窗并传递对象引用
        showPopup(box.userData, event, box);
      }
    } else {
      // 点击的不是盒子或货架，关闭弹窗
      if (popup) {
        popup.classList.add('hidden');
      }
      resetSelection();
    }
  } else {
    // 点击空白处，清除选中状态并关闭弹窗
    resetSelection();
    if (popup) {
      popup.classList.add('hidden');
    }
  }

  // 阻止事件冒泡（避免触发其他可能的事件处理）
  event.stopPropagation();
}

// 重置选中状态
function resetSelection () {
  // 重置货架选中状态
  if (selectedLocation) {
    selectedLocation.children.forEach(child => {
      if (child.material && !child.material.wireframe) {
        child.material.color.setHex(0x4a5568);
      }
    });
    selectedLocation = null;
  }

  // 重置箱子选中状态
  if (selectedBox) {
    selectedBox.material.color.setHex(selectedBox.userData.originalColor || 0xe6c66e);
    selectedBox = null;
  }
}

// 显示货架信息
function showLocationInfo (data) {
  const infoDiv = document.getElementById('locationInfo');
  if (infoDiv) {
    infoDiv.innerHTML = `
            <div class="bg-white p-4 rounded-lg shadow">
                <h3 class="text-lg font-medium mb-2">货位信息</h3>
                <p class="mb-1"><span class="font-medium">货位号:</span> ${data.location}</p>
                <p class="mb-1"><span class="font-medium">状态:</span> 
                    <span class="inline-block px-2 py-1 text-sm rounded ${data.status === '空闲' ? 'bg-green-100 text-green-800' : 'bg-orange-100 text-orange-800'}">${data.status}</span>
                </p>
            </div>
        `;
    infoDiv.style.display = 'block';
  }
}
function updatePopupPosition () {
  if (!selectedBox || !renderer || !camera) return;

  const popup = document.getElementById('popup');
  if (!popup) return;

  // 获取盒子在屏幕上的位置
  const boxPosition = selectedBox.position.clone();
  boxPosition.y += 1; // 在盒子上方显示弹窗

  const vector = boxPosition.project(camera);

  // 转换到屏幕坐标
  const widthHalf = 0.5 * renderer.domElement.clientWidth;
  const heightHalf = 0.5 * renderer.domElement.clientHeight;

  vector.x = (vector.x * widthHalf) + widthHalf;
  vector.y = -(vector.y * heightHalf) + heightHalf;

  // 设置弹窗位置
  popup.style.transform = `translate(${vector.x}px, ${vector.y}px)`;
}
// 替换原有的 showLocationInfo 和 showBoxInfo 函数
function showPopup (data, event, object) {
  const popup = document.getElementById('popup');
  const popupContent = document.getElementById('popupContent');
  if (!popup || !popupContent) return;

  // 设置弹窗内容（保持不变）
  if (data.type === 'shelf') {
    popupContent.innerHTML = `
      <h3 class="text-lg">货位信息</h3>
      <p class="text-lg"><span class="font-medium">货位号:</span> ${data.location}</p>
      <p class="text-lg"><span class="font-medium">状态:</span> ${data.status}</span></p>
    `;
  } else if (data.type === 'box') {
    popupContent.innerHTML = `
      <p class="text-lg text-top">货品信息</p>
      <p class="text-lg"><span class="font-medium">货位号:&nbsp;</span> ${data.location}</p>
      <p class="text-lg"><span class="font-medium">产品名称:&nbsp;</span> ${data.productName}</p>
      <p class="text-lg"><span class="font-medium">数量:&nbsp;</span> ${data.quantity}件</p>
      <p class="text-lg"><span class="font-medium">状态:&nbsp;</span> ${data.status}</span></p>
    `;
  }

  // 保存当前选中对象
  selectedBox = object;

  // 初始位置设置
  updatePopupPosition();

  popup.classList.remove('hidden');
}

// 隐藏信息面板
function hideInfo () {
  const infoDiv = document.getElementById('locationInfo');
  if (infoDiv) {
    infoDiv.style.display = 'none';
  }
}

// 创建AGV模型
function createAGV (x, y, z) {
  const agv = new THREE.Group();

  // AGV底盘
  const baseGeometry = new THREE.BoxGeometry(1.2, 0.2, 1.6);
  const baseMaterial = new THREE.MeshStandardMaterial({
    color: 0x2c5282, // 深蓝色
    metalness: 0.7,
    roughness: 0.3
  });
  const base = new THREE.Mesh(baseGeometry, baseMaterial);
  base.position.y = 0.1;
  agv.add(base);

  // AGV顶部
  const topGeometry = new THREE.BoxGeometry(1, 0.1, 1.4);
  const topMaterial = new THREE.MeshStandardMaterial({
    color: 0x4299e1, // 亮蓝色
    metalness: 0.6,
    roughness: 0.4
  });
  const top = new THREE.Mesh(topGeometry, topMaterial);
  top.position.y = 0.25;
  agv.add(top);

  // 添加轮子
  const wheelGeometry = new THREE.CylinderGeometry(0.15, 0.15, 0.1, 16);
  const wheelMaterial = new THREE.MeshStandardMaterial({
    color: 0x1a202c,
    metalness: 0.8,
    roughness: 0.2
  });

  // 四个轮子的位置
  const wheelPositions = [
    [-0.5, 0.15, 0.6],  // 左前
    [0.5, 0.15, 0.6],   // 右前
    [-0.5, 0.15, -0.6], // 左后
    [0.5, 0.15, -0.6]   // 右后
  ];

  wheelPositions.forEach(pos => {
    const wheel = new THREE.Mesh(wheelGeometry, wheelMaterial);
    wheel.position.set(...pos);
    wheel.rotation.z = Math.PI / 2;
    agv.add(wheel);
  });

  // 添加警示灯
  const lightGeometry = new THREE.BoxGeometry(0.1, 0.1, 0.1);
  const lightMaterial = new THREE.MeshStandardMaterial({
    color: 0xf6e05e,
    emissive: 0xf6e05e,
    emissiveIntensity: 0.5
  });
  const light = new THREE.Mesh(lightGeometry, lightMaterial);
  light.position.set(0, 0.35, 0);
  agv.add(light);

  // 设置AGV位置
  agv.position.set(x, y, z);
  agv.castShadow = true;
  agv.receiveShadow = true;

  // 添加AGV信息
  agv.userData = {
    type: 'agv',
    speed: 0.05,
    targetIndex: 0,
    lightOn: true
  };

  return agv;
}

// 初始化AGV路径点
const agvPathPoints = [
  new THREE.Vector3(-22, 0, -22), // 左下角
  new THREE.Vector3(-22, 0, 22),  // 左上角
  new THREE.Vector3(22, 0, 22),   // 右上角
  new THREE.Vector3(22, 0, -22)   // 右下角
];

// 更新AGV位置和动画
function updateAGVs () {
  agvs.forEach((agv, index) => {
    const currentTarget = agvPathPoints[agv.userData.targetIndex];
    const direction = new THREE.Vector3().subVectors(currentTarget, agv.position);

    if (direction.length() < 0.1) {
      // 到达目标点，更新下一个目标
      agv.userData.targetIndex = (agv.userData.targetIndex + 1) % agvPathPoints.length;
    } else {
      // 移动AGV
      direction.normalize();
      agv.position.add(direction.multiplyScalar(agv.userData.speed));

      // 计算AGV朝向
      const angle = Math.atan2(direction.x, direction.z);
      agv.rotation.y = angle;
    }

    // 更新警示灯
    const light = agv.children.find(child => child.material && child.material.emissive);
    if (light) {
      agv.userData.lightOn = !agv.userData.lightOn;
      light.material.emissiveIntensity = agv.userData.lightOn ? 0.5 : 0.2;
    }
  });
}

// 动画循环
function animate () {
  animationFrameId = requestAnimationFrame(animate);

  if (controls) {
    controls.update();
  }

  // 更新AGV位置和动画
  updateAGVs();

  // 如果有弹窗显示，则更新其位置
  const popup = document.getElementById('popup');
  if (popup && !popup.classList.contains('hidden') && selectedBox) {
    updatePopupPosition();
  }

  if (renderer && scene && camera) {
    renderer.render(scene, camera);
  }
}